<template>
  <div class="todo-container">
    <p>父组件:全部{{ todos }}</p>
    <p>父组件:完成{{ todoIsDone }}</p>
    <div class="todo-wrap">
      <!-- <todo-header :addTodo="addTodo"></todo-header> -->

       <!-- 
          底下的写法：
               事件源:给todo-header组件实例绑定一个自定义事件addTodo
               事件类型:addTodo
               事件的回调:addTodo函数
        -->
      <todo-header @addTodo="addTodo"></todo-header>

      <!--父子组件通信:props利用 自定义属性 的形式将数据传递给子组件-->
      <todo-main
        :todos="todos"
        :updateTodoDone="updateTodoDone"
        :deleteTodo="deleteTodo"
      ></todo-main>

      <todo-footer
        :todos="todos"
        :todoIsDone="todoIsDone"
        :updateAllTodoDone="updateAllTodoDone"
        :deleteTodoIsDone="deleteTodoIsDone"
      ></todo-footer>
    </div>
  </div>
</template>

<script>
//三个子组件
import TodoHeader from "./components/TodoHeader.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoFooter from "./components/TodoFooter.vue";
export default {
  name: "",
  //数据有父组件统一管理,三个兄弟组件使用的都是父组件的数据
  data() {
    return {
      //todos:代表的是事情 title事情名字  done:代表这件事情做还是没做 true：做完、false：没做
      //响应式数据:对象与数组的区别   对象:在data当中定义的对象属性[K]都是响应式的  数组:变更、替换
      todos: JSON.parse(localStorage.getItem("TODOS"))||[],
    };
  },
  components: {
    TodoHeader,
    TodoMain,
    TodoFooter,
  },
  methods: {
    //修改某一件事情完成的状态
    //第一种写法:将修改事件整个对象传递回来
    //第二种写法:将修改事件的索引值回传
    //第三种写法:传递修改元素的ID
    updateTodoDone(id) {
      //父组件要修改自身数据--勾选状态
      //第一种情况的写法
      // item.done = !item.done;

      //第二种情况写法:数组里面的对象K都是响应式的
      // this.todos[index].done = !this.todos[index].done;   这种写法:修改对象的属性的属性值  [对象K都是响应式的]
      // this.todos[index] = {id:2,title:'睡觉',done:true};  这种写法:操作数组,变更、替换 ，这种写不可以

      //第三种写法:通过找到相应的数组里面对象，操作对象[对象K都是响应式的]
      // let obj = this.todos.find((item=>{
      //       return item.id===id;
      // }));
      // obj.done = !obj.done;

      //数组的替换:数组检测,变更、替换
      // this.todos = this.todos.map((item) => {
      //   if (item.id == id) {
      //     return {
      //       ...item,
      //       done: !item.done,
      //     };
      //   }
      //   return item;
      // });
      //数组的替换
      this.todos = this.todos.map((item) =>
        item.id == id ? { ...item, done: !item.done } : item
      );
    },
    //删除选中的元素
    //第一种索引值 + 变更方法 splice
    //第二种相应元素(对象) + 变更方法   splice
    //第三中写法:id  + 替换  filter
    deleteTodo(id) {
      //第一种写法:
      //变更,变更[shift|unshift|push|pop|reverse|splice|sort]、替换
      // this.todos.splice(index,1);
      // this.todos.splice(this.todos.indexOf(item),1);
      //第二种写法:替换
      this.todos = this.todos.filter((item) => item.id != id);
      //这种写法不建议:这种写法程序员最后的底线！！！
      // let arr = [];
      // for (var i = 0; i < this.todos.length; i++) {
      //   if (this.todos[i].id != id) {
      //     arr.push(this.todos[i]);
      //   }
      // }
      // //替换
      // this.todos = arr;
    },
    //添加一个事情的事件
    addTodo(todo) {
      //子组件将新增的事件，传递给父组件,父组件添加一个新的元素！！！
      //非法的情况:事件名称不能为空
      if (todo.title.trim() == "") {
        alert("亲爱的添加的事件名称不能为空的");
        //函数体中遇见关键字return后面语句不在执行
        return;
      }
      //非法情况2:添加新的元素的时候,要确保事情，在数组当中没有出现！！！如果从出现重复不应该添加！！！
      let repeat = this.todos.find((item) => item.title == todo.title);
      //代表新增的事件，在数组当中出现，不应该在添加！！！
      if (repeat) {
        alert("亲爱的此事件已经有了,不能在添加了");
        return;
      }
      //变更
      this.todos.unshift(todo);
    },
    //全选,修改全部事件的勾选的状态
    updateAllTodoDone(done) {
      //修改父组件数据，勾选状态
      //替换:map会返回一个新的数组
      // this.todos = this.todos.map((item) => ({...item,done}));

      //对象的写法:相当于for循环遍历遍历数组里面每一个元素[对象，在修改对象的属性值而已]
      this.todos.forEach((item) => {
        item.done = done;
      });
    },
    //删除掉已经完成的事件
    deleteTodoIsDone() {
      //数组的替换
      this.todos = this.todos.filter((item) => {
        return !item.done;
      });
    },
  },
  //计算属性:给当前VC添加计算出一个新的属性与属性值[利用已有的属性与属性值]
  computed: {
    //父组件将已经完成的事件计算出来！！！
    todoIsDone() {
      //计算属性:函数返回结果即为这个属性的属性值
      return this.todos.filter((item) => item.done);
    },
  },
  //监听属性的变化
  watch: {
    //如果是数组的变更|或者是替换可以监听到！！
    //Vue检测数据变化:数组的替换、变更就算不是深度监听可以检测到变化！！！
    todos: {
      deep: true,
      handler() {
         //立马本地存储持久化存储数据
         localStorage.setItem("TODOS",JSON.stringify(this.todos));
      },
    },
  },
};
</script>

<style scoped>
</style>
